/**
*  \file seppuku.c
*
*  \brief  	Delayed Reset
*
*  \author	Michael J. Hohmann <michael.hohmann@linde-mh.de>
*
*
*/

/*===============================================[ private includes  ]================================================*/
#include "seppuku.h"
#include <string.h>
#include "../tasklet/tasklet.h"
#include "../pal/pal_mem.h"
/*===============================================[ private defines   ]================================================*/

/*===============================================[ private datatypes ]================================================*/

/*===============================================[ private variables ]================================================*/
/** Local Variables */
static struct
{
   BO aktive;                      /**< Count down will be done if flag is true */
   U32 count_down;                 /**< Value will be count down and seppuku will be done if value is 0 */
   struct tasklet service_tasklet;
   void (*reset_function) (void);
   U32 *ptr_reset_reason_addr;
   U32 current_reset_reason;
} seppuku;

/*===============================================[ public variables  ]================================================*/

/*===============================================[ private functions ]================================================*/
static void seppuku_service( struct tasklet *task );

/*====================================================================================================================*/

/**
*  Initialization.
*
*  Initialize the seppuku module.
*
*  \return RC_SUCCESS if successful.
*/
RC seppuku_initialize( struct tasklet_list * const list, void (*reset_function)(void), U32 * const reset_reason_addr )
{
   if (   ( NULL == list)
       || ( NULL == reset_function)
      )
   {
      return RC_ERROR_NULL;
   }

   pal_memzero( &seppuku, sizeof(seppuku) );
   seppuku.reset_function = reset_function;
   seppuku.ptr_reset_reason_addr = reset_reason_addr;
   seppuku.current_reset_reason = U32_CONST(0);
   tasklet_assign( list , &seppuku.service_tasklet, seppuku_service, NULL );

   return RC_SUCCESS;
}

void seppuku_perform( const U32 delay, const U32 reset_reason )
{
   if ( ! seppuku.aktive )
   {
      seppuku.current_reset_reason = reset_reason;
      seppuku.count_down = delay;
      seppuku.aktive = TRUE;
   }
}

static void seppuku_service( struct tasklet * task )
{
   UNREFERENCED(task);

   if ( seppuku.aktive )
   {
      if ( U32_CONST(0) == seppuku.count_down )
      {
         if ( NULL != seppuku.ptr_reset_reason_addr )
         {
            *(seppuku.ptr_reset_reason_addr) = seppuku.current_reset_reason;
         }

         seppuku.reset_function();
      }

      seppuku.count_down--;
   }
}

/***********************************************************************************************************************
*                             Copyright 2011 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
